package com.gqh.weather.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.gqh.weather.domain.dto.*;
import com.gqh.weather.domain.entity.*;
import com.gqh.weather.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.type.TypeReference;

/**
 * @description 教育质量评价报告服务类
 * @author AI
 * @date 2025-11-07
 */
@Service
public class ReportService {
    
    @Autowired
    private TaskMapper taskMapper;
    
    @Autowired
    private TaskSchoolRecordMapper taskSchoolRecordMapper;
    
    @Autowired
    private SchoolMapper schoolMapper;
    
    @Autowired
    private CityMapper cityMapper;

    @Autowired
    private PcSubtaskMapper pcSubtaskMapper;;
    @Autowired
    private StudentMapper studentMapper;;

    @Autowired
    private PaperMapper paperMapper;

    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 数据总览
     *
     * @param taskId 评价任务id
     * @param citycode 城市码
     * @param bSchool 是否学校级别
     * @return 数据总览结果
     */
    public Object overview(Integer taskId, String citycode, boolean bSchool) {
        // TODO: 实现数据总览逻辑
        return new Object();
    }

    /**
     * 学业发展水平
     *
     * @param taskId 评价任务id
     * @param citycode 城市码
     * @param bSchool 是否学校级别
     * @return 学业发展水平结果
     */
    public ReportResult xueye(Integer taskId, String citycode, boolean bSchool) {
        // 验证taskId
        Task taskInfo = taskMapper.selectById(taskId);
        if (taskInfo == null) {
            throw new RuntimeException("评价任务不存在");
        }
        if (taskInfo.getState() != 2) {
            throw new RuntimeException("该评价任务还未结束");
        }
        
        // 取出所有学校评分记录
        List<String> codes = new ArrayList<>();
        if (!bSchool) {
            // 获取子区域城市码
            codes = cityMapper.selectChildrenCodesByCode(citycode);
        } else {
            codes.add(citycode);
        }
        
        List<TaskSchoolRecord> records = getTaskSchoolRecord(taskId, codes);
        
        ReportResult res = new ReportResult();
        res.setTotalData(new ReportTotalData());
        res.setSubData(new ArrayList<>());
        res.setPercent(new ArrayList<>());
        
        if (records.isEmpty()) {
            return res;
        }
        
        // 计算total_data
        res.setTotalData(countTotalData(2, records));
        
        // 计算subdata
        if (bSchool) {
            List<ReportSubData> reportSubData = new ArrayList<>();
            Set<Integer> schoolIds = new HashSet<>();
            Map<Integer, List<TaskSchoolRecord>> schoolRecords = new HashMap<>();
            
            for (TaskSchoolRecord record : records) {
                schoolRecords.computeIfAbsent(record.getSchoolId(), k -> new ArrayList<>()).add(record);
                schoolIds.add(record.getSchoolId());
            }
            
            List<School> schoolInfos = schoolMapper.selectBatchIds(schoolIds);
            
            for (Map.Entry<Integer, List<TaskSchoolRecord>> entry : schoolRecords.entrySet()) {
                Integer schoolId = entry.getKey();
                List<TaskSchoolRecord> schoolRecord = entry.getValue();
                
                ReportTotalData regionTotalData = countTotalData(2, schoolRecord);
                
                for (School sInfo : schoolInfos) {
                    if (sInfo.getId().equals(schoolId)) {
                        ReportSubData subData = new ReportSubData();
                        subData.setSchoolName(sInfo.getName());
                        subData.setSchoolId(schoolId);
                        subData.setITotalScore(regionTotalData.getITotalScore());
                        subData.setTotalScore(regionTotalData.getTotalScore());
                        subData.setAverageScoreList(new ArrayList<>(regionTotalData.getAverageScoreList()));
                        reportSubData.add(subData);
                        break;
                    }
                }
            }
            res.setSubData(reportSubData);
        } else {
            List<City> regions = new ArrayList<>();
            for (String code : codes) {
                City city = cityMapper.selectByCode(code);
                if (city != null) {
                    regions.add(city);
                }
            }
            
            Map<String, City> regionMap = new HashMap<>();
            for (City region : regions) {
                regionMap.put(region.getCode(), region);
            }
            
            List<ReportSubData> reportSubData = new ArrayList<>();
            for (String k : regionMap.keySet()) {
                List<TaskSchoolRecord> regionRecord = getTaskSchoolRecord(taskId, Arrays.asList(k));
                ReportTotalData regionTotalData = countTotalData(2, regionRecord);
                
                ReportSubData subData = new ReportSubData();
                subData.setCityname(regionMap.get(k).getName());
                subData.setCitycode(k);
                subData.setITotalScore(regionTotalData.getITotalScore());
                subData.setTotalScore(regionTotalData.getTotalScore());
                subData.setAverageScoreList(new ArrayList<>(regionTotalData.getAverageScoreList()));
                reportSubData.add(subData);
            }
            res.setSubData(reportSubData);
        }
        
        // 计算折算分 百分比 良好率 & 及格率 & 不及格率
        for (ReportSubData sd : res.getSubData()) {
            // 学业发展水平折算分为: ITotalScore * 35 / 400
            sd.setIZhesuanScore(roundPrecision(sd.getITotalScore() * 35 / 400, 2));
            sd.setZhesuanScore(String.valueOf(sd.getIZhesuanScore()));
            
            if (sd.getAverageScoreList() != null && !sd.getAverageScoreList().isEmpty()) {
                ReportPercent percent = new ReportPercent();
                if (sd.getCitycode() != null && !sd.getCitycode().isEmpty()) {
                    percent.setCityname(sd.getCityname());
                    percent.setCitycode(sd.getCitycode());
                } else {
                    percent.setSchoolName(sd.getSchoolName());
                    percent.setSchoolId(sd.getSchoolId());
                }
                percent.setAverageScoreList(sd.getAverageScoreList());
                res.getPercent().add(percent);
            }
        }
        
        return res;
    }

    /**
     * 四舍五入到指定精度
     *
     * @param value 值
     * @param precision 精度
     * @return 四舍五入后的值
     */
    private double roundPrecision(double value, int precision) {
        BigDecimal bd = new BigDecimal(Double.toString(value));
        bd = bd.setScale(precision, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }
    
    /**
     * 获取任务学校记录
     *
     * @param taskId 任务ID
     * @param codes 城市码列表
     * @return 任务学校记录列表
     */
    private List<TaskSchoolRecord> getTaskSchoolRecord(Integer taskId, List<String> codes) {
        if (codes.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 根据城市码获取学校列表
        LambdaQueryWrapper<School> schoolWrapper = new LambdaQueryWrapper<>();
        schoolWrapper.in(School::getCitycode, codes);
        List<School> schoolList = schoolMapper.selectList(schoolWrapper);
        
        if (schoolList.isEmpty()) {
            return new ArrayList<>();
        }
        
        List<Integer> schoolIds = new ArrayList<>();
        for (School school : schoolList) {
            schoolIds.add(school.getId());
        }
        
        // 根据任务ID和学校ID列表获取记录
        LambdaQueryWrapper<TaskSchoolRecord> recordWrapper = new LambdaQueryWrapper<>();
        recordWrapper.eq(TaskSchoolRecord::getTaskId, taskId);
        recordWrapper.in(TaskSchoolRecord::getSchoolId, schoolIds);
        return taskSchoolRecordMapper.selectList(recordWrapper);
    }
    
    /**
     * 计算总数据
     *
     * @param categoryId 类别ID
     * @param records 记录列表
     * @return 报告总数据
     */
    private ReportTotalData countTotalData(int categoryId, List<TaskSchoolRecord> records) {
        ReportTotalData totalData = new ReportTotalData();
        totalData.setAverageScoreList(new ArrayList<>());
        
        Set<Integer> schoolMaps = new HashSet<>();
        List<CategoryScoreData> recDatas = new ArrayList<>();

        if (records == null || records.isEmpty()) {
            return totalData;
        }
        
        // 解析records中的result JSON字段
        for (TaskSchoolRecord record : records) {
            try {
                if (record.getResult() != null && !record.getResult().isEmpty()) {
                    // 解析JSON数据: map[int][]*CategoryScoreData
                    Map<Integer, List<CategoryScoreData>> recData = objectMapper.readValue(
                        record.getResult(), 
                        new TypeReference<Map<Integer, List<CategoryScoreData>>>(){}
                    );
                    
                    // 获取指定分类的数据
                    List<CategoryScoreData> categoryData = recData.get(categoryId);
                    if (categoryData != null) {
                        recDatas.addAll(categoryData);
                    }
                }
                schoolMaps.add(record.getSchoolId());
            } catch (Exception e) {
                // 忽略解析错误
                e.printStackTrace();
            }
        }
        
        // 合并相同分类的数据
        Map<Integer, CategoryScoreData> mergedData = new HashMap<>();
        for (CategoryScoreData rec : recDatas) {
            CategoryScoreData existing = mergedData.get(rec.getCategoryId());
            if (existing != null) {
                // 合并数据
                existing.setStudentNum(existing.getStudentNum() + rec.getStudentNum());
                existing.setScore(existing.getScore() + rec.getScore());
                existing.setE(existing.getE() + rec.getE());
                existing.setG(existing.getG() + rec.getG());
                existing.setP(existing.getP() + rec.getP());
                existing.setF(existing.getF() + rec.getF());
            } else {
                // 创建新的数据项
                CategoryScoreData newData = new CategoryScoreData();
                newData.setCategoryId(rec.getCategoryId());
                newData.setCategoryName(rec.getCategoryName());
                newData.setStudentNum(rec.getStudentNum());
                newData.setScore(rec.getScore());
                newData.setE(rec.getE());
                newData.setG(rec.getG());
                newData.setP(rec.getP());
                newData.setF(rec.getF());
                mergedData.put(rec.getCategoryId(), newData);
            }
        }
        
        // 将合并后的数据转换为ReportCategoryScoreData并添加到结果列表中
        List<ReportCategoryScoreData> reportDataList = new ArrayList<>();
        for (CategoryScoreData categoryScoreData : mergedData.values()) {
            ReportCategoryScoreData reportData = new ReportCategoryScoreData();
            reportData.setScore(categoryScoreData.getScore());
            reportData.setCategoryId(categoryScoreData.getCategoryId());
            reportData.setCategoryName(categoryScoreData.getCategoryName());
            reportData.setStudentNum(categoryScoreData.getStudentNum());
            reportData.setE(categoryScoreData.getE());
            reportData.setG(categoryScoreData.getG());
            reportData.setP(categoryScoreData.getP());
            reportData.setF(categoryScoreData.getF());
            
            // 计算平均分，参考Go代码逻辑
            if (categoryScoreData.getStudentNum() > 0) {
                double iAverageScore = roundPrecision(categoryScoreData.getScore() / categoryScoreData.getStudentNum(), 2);
                reportData.setIAverageScore(iAverageScore);
                reportData.setAverageScore(String.valueOf(iAverageScore));
            }
            
            reportDataList.add(reportData);
        }
        totalData.getAverageScoreList().addAll(reportDataList);
        
        // 计算总分和其他统计数据
        double totalScore = 0.0;
        for (ReportCategoryScoreData avg : totalData.getAverageScoreList()) {
            // 计算优良率等，参考Go代码逻辑
            double totalEgpf = avg.getE() + avg.getG() + avg.getP() + avg.getF();
            if (totalEgpf > 0) {
                avg.setE((int) Math.round(avg.getE() * 100 / totalEgpf));
                avg.setG((int) Math.round(avg.getG() * 100 / totalEgpf));
                avg.setP((int) Math.round(avg.getP() * 100 / totalEgpf));
                avg.setF((int) Math.round(avg.getF() * 100 / totalEgpf));
            }
            
            if (avg.getCategoryId() != 9999999) {
                totalScore += avg.getIAverageScore();
            }
        }
        
        totalData.setITotalScore(totalScore);
        totalData.setTotalScore(String.valueOf(totalScore));

        Integer taskId = records.get(0).getTaskId();
        PcSubtask pcSubtask = pcSubtaskMapper.selectByPid(taskId);

        // 解析schedule字段中的TaskSchedule列表
        List<TaskSchedule> schedules = null;
        try {
            schedules = objectMapper.readValue(
                    pcSubtask.getSchedule(),
                    new TypeReference<List<TaskSchedule>>() {}
            );
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

        List<Integer> paperIds = schedules.stream().map(TaskSchedule::getPaperId).toList();
        List<Paper> papers = paperMapper.selectBatchIds(paperIds);
        int totalFullScore = papers.stream().mapToInt(Paper::getScore).sum();

        Long studentNum = studentMapper.selectCount(Wrappers.lambdaQuery(Student.class)
                .eq(Student::getTaskId, taskId)
                .in(Student::getSchoolId, records.stream().map(TaskSchoolRecord::getSchoolId).toList()));

        totalData.setTotalFullScore(String.valueOf(totalFullScore));

        return totalData;
    }

    /**
     * 体质健康水平
     *
     * @param taskId 评价任务id
     * @param citycode 城市码
     * @param bSchool 是否学校级别
     * @return 体质健康水平结果
     */
    public Object health(Integer taskId, String citycode, boolean bSchool) {
        // TODO: 实现实体健康水平逻辑
        return new Object();
    }

    /**
     * 心理健康水平
     *
     * @param taskId 评价任务id
     * @param citycode 城市码
     * @param bSchool 是否学校级别
     * @return 心理健康水平结果
     */
    public Object mental(Integer taskId, String citycode, boolean bSchool) {
        // TODO: 实现心理健康水平逻辑
        return new Object();
    }

    /**
     * 艺术素质水平
     *
     * @param taskId 评价任务id
     * @param citycode 城市码
     * @param bSchool 是否学校级别
     * @return 艺术素质水平结果
     */
    public Object art(Integer taskId, String citycode, boolean bSchool) {
        // TODO: 实现艺术素质水平逻辑
        return new Object();
    }
}